package sample;

import java.awt.*;
import java.io.*;
import java.security.GeneralSecurityException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public final class FileChooserSample extends Application {

    private final Desktop desktop = Desktop.getDesktop();

    public static void main(String[] args) {
        Application.launch(args);
    }

    public static String Path = "user.dir";

    @Override
    public void start(final Stage stage) {
        stage.setTitle("excel 批量加解密");
        stage.setWidth(300);
        stage.setHeight(150);

        final FileChooser fileChooser = new FileChooser();

        final TextField textField = new TextField("请先输入密码！");
        final Button openMultipleButton = new Button("解密");
        final Button openMultipleButton2 = new Button("加密");
        final Alert alert = new Alert(Alert.AlertType.ERROR);
        final Alert info = new Alert(Alert.AlertType.INFORMATION);


        List<Object> errorList1 = new ArrayList<>();
        openMultipleButton2.setOnAction((final ActionEvent event) -> {
            configureFileChooser(fileChooser);
            List<File> list = fileChooser.showOpenMultipleDialog(stage);
            if (list != null) {
                Path = list.get(0).getParent();
                String pwd = textField.getText();//获取密码
                list.forEach(file -> {
                    try {
                        String excelFile = file.toString();
                        encrypt(excelFile, pwd);//加密
                    } catch (Exception e) {
                        System.err.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"==== 加密 错误 == >" + file.getName()+"===password==="+pwd);
                        alert.setTitle("错误");
                        errorList1.add(file.getName());
                    }
                });
                if (errorList1.size() != 0) {
                    alert.setTitle("错误");
                    alert.setHeaderText(null);
                    alert.setContentText("   加密错误！查看日志");
                    alert.showAndWait();
                } else {
                    info.setTitle("完成");
                    info.setHeaderText(null);
                    info.setContentText("   加密完成！");
                    info.showAndWait();
                }
            }

        });
        //解密
        List<Object> errorList = new ArrayList<>();
        openMultipleButton.setOnAction((final ActionEvent e) -> {
            configureFileChooser(fileChooser);
            List<File> list = fileChooser.showOpenMultipleDialog(stage);
            if (list != null) {
                Path = list.get(0).getParent();
                String pwd = textField.getText();//获取密码
                list.forEach(file -> {
                    try {
                        String excelFile = file.toString();
                        decrypt(excelFile, pwd);//解密
                    } catch (Exception exception) {
                        System.err.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"==== 解密 错误 == >" + file.getName()+"===password==="+pwd);
                        errorList.add(file.getName());
//                                exception.printStackTrace();
                    }
                });
                if (errorList.size() != 0) {
                    alert.setTitle("错误");
                    alert.setHeaderText(null);
                    alert.setContentText("   解密错误！查看日志");
                    alert.showAndWait();
                } else {
                    info.setTitle("完成");
                    info.setHeaderText(null);
                    info.setContentText("   解密完成！");
                    info.showAndWait();
                }


            }
        });

        final GridPane inputGridPane = new GridPane();

//        GridPane.setConstraints(openButton, 0, 1);
        GridPane.setConstraints(openMultipleButton, 1, 0);
        GridPane.setConstraints(textField, 0, 0);
        GridPane.setConstraints(openMultipleButton2, 2, 0);
        inputGridPane.setHgap(6);
        inputGridPane.setVgap(6);

        inputGridPane.getChildren().addAll(textField, openMultipleButton, openMultipleButton2);

        final Pane rootGroup = new VBox(12);
        rootGroup.getChildren().addAll(inputGridPane);
        rootGroup.setPadding(new Insets(12, 12, 12, 12));

        stage.setScene(new Scene(rootGroup));
        stage.show();
    }


    private static void configureFileChooser(
            final FileChooser fileChooser) {
        fileChooser.setTitle("选择xlsx文件(可Ctrl+A全选)");

//        System.out.println(Path);
        if (Path.equals("user.dir")) {
            fileChooser.setInitialDirectory(new File(System.getProperty(Path)));
        } else {
            fileChooser.setInitialDirectory(new File(Path));
        }
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("All XLSX", "*.xlsx")
//                new FileChooser.ExtensionFilter("JPG", "*.jpg"),
//                new FileChooser.ExtensionFilter("PNG", "*.png")
        );
    }


    //去除密码

    /**
     * @param file 目标文件
     * @param pwd  原密码
     * @throws IOException
     * @throws GeneralSecurityException
     */
    public static void decrypt(String file, String pwd) throws IOException, GeneralSecurityException {
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"=====解密 xlsx====" + file+" ==== password ====> "+pwd);
        Workbook workbook;
        InputStream inp = new FileInputStream(file);
        POIFSFileSystem pfs = new POIFSFileSystem(inp);
        inp.close();
        EncryptionInfo encInfo = new EncryptionInfo(pfs);
        Decryptor decryptor = Decryptor.getInstance(encInfo);
        decryptor.verifyPassword(pwd);
        workbook = new XSSFWorkbook(decryptor.getDataStream(pfs));
//        String fileName = file.getName();
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        workbook.close();
    }

//加密

    public static void encrypt(String FILE, String password) throws IOException, InvalidFormatException, GeneralSecurityException {
        if (FILE.toLowerCase().endsWith("xlsx")) {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"=====解密 xlsx====" + FILE+" ==== password ====> "+password);
            File file = new File(FILE);
            String fileName = file.getName();
            // 设置密 码 保 护 ·
            POIFSFileSystem fs = new POIFSFileSystem();
            EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
            Encryptor enc = info.getEncryptor();
            //设置密码
            enc.confirmPassword(password);
            //加密文件
            OPCPackage opc = OPCPackage.open(new File(FILE), PackageAccess.READ_WRITE);
            OutputStream os = enc.getDataStream(fs);
            opc.save(os);
            opc.close();
            // 这一步特别注意，导出之前一定要先关闭加密文件流，不然导出文件会损坏而无法打开
            os.close();
            //把加密后的文件写回到流
//            String outputPath = FILE ;
            FileOutputStream fos = new FileOutputStream(FILE);
            fs.writeFilesystem(fos);
            fos.close();
        } else {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"=====解密 xlsx====" + FILE+" ==== password ====> "+password);
            File file = new File(FILE);
            String fileName = file.getName();
            POIFSFileSystem poif = new POIFSFileSystem(new FileInputStream(FILE));
            HSSFWorkbook wb = new HSSFWorkbook(poif);
            // 设置密 码 保 护 ·
            Biff8EncryptionKey.setCurrentUserPassword(password);
            wb.writeProtectWorkbook(Biff8EncryptionKey.getCurrentUserPassword(), "管理员");
            wb.unwriteProtectWorkbook();
            // 写入excel文件
            String outputPath = FILE + "\\" + fileName;
            FileOutputStream fileOut = new FileOutputStream(outputPath);
            wb.write(fileOut);
            fileOut.close();
        }
    }
}